home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- /*
- * Kurt Akeley
- * 4 June 1987
- *
- * Utility routines to implement awk programs in C
- *
- * Changes from version 1:
- *
- * 1. All references to 'group' are changed to 'array'.
- * 2. It is no longer necessary to specify maximum 'array' size.
- * Rather, arrays grow as necessary.
- * 3. Added POINTER type (in addition to INDEX,INT,FLOAT,STRING).
- * 4. Increased all maximum values.
- * 5. Index() renamed sindex().
- * 6. Command line FS specification added.
- * 7. 4/12/89 KBA - changed getpointer to return 0 if not found.
- * getstring still returns "" in this case.
- * 8. 5/6/89 KBA - changed argv treatment to ignore null fields
- * 9. 11/91 KBA - closed files immediately, rather than when the
- * next file is opened.
- * 10. 11/91 KBA - added numeric keys
- * 11. 11/91 KBA - prefixed all visible routine names with "awk"
- * words in names now capitalized in GL 5.0 manner
- */
-
- #include <stdio.h>
- #include <awk.h>
-
- #define NOTFATAL 0
- #define AWKFATAL 1
-
- #define VERSION "3.0"
- #define DATE "18 November 1991"
-
- #define MAXARG 0x100
- #define MAXARGLEN 0x1000
- #define MAXSTR 0x100
- #define MAXKEYLEN MAXSTR
- #define MAXARRAY 0x100
- #define INITIALSIZE 0x100
- #define REMAIN(i) (6*(i)) / 10 - 1;
-
- /*
- * Visible global variable declarations
- */
- int awkNF; /* number of fields in current line */
- int awkNL; /* line number in currently open file */
- int awkNR; /* number of current record - all files */
- int awkFS; /* field separator character */
- int awkRS; /* record separator character */
- char awkFILENAME[MAXSTR+2]; /* filename of currently open file */
- char *awkARG[MAXARG+2]; /* pointers to argument strings */
-
- /*
- * Internal global variable declarations
- */
- static char line[MAXARGLEN+2];
- static char args[MAXARGLEN+2];
- static FILE *infile = 0;
- static int ARGC;
- static char **ARGV;
- static char es[200];
- static hashval[128];
- static int DEBUG;
- static int STAT;
- static int awkinited = 0;
- static int filecount = 0;
-
- /*
- * Internal diagnostic variable declarations
- */
- #ifdef METER
- static int access, search, storage;
- static AwkArray *arraylist[MAXARRAY];
- static int arraycount = 0;
- #endif
-
- /*
- * Internal procedure and function definitions
- */
- static void awkopen (char *s);
- static int awkopennext(void);
- static void awkclose (void);
- static void error (int class, char *s);
- static void expandarray (AwkArray *array);
- static int hash (AwkArray *array, register char *key);
- static AwkArray *newarray (AwkArray *array);
- static char *newstring (char *s);
-
- /*
- * Diagnostic procedure and function definitions
- */
- void _awk_seearray (AwkArray *array);
- void _awk_statall (void);
-
- /*
- * Visible procedures and functions
- */
-
- void awkAddFloat (AwkArray *array, char *key, float f) {
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkAddFloat called prior to awkInit");
- if (array == 0)
- error (AWKFATAL, "awkAddFloat: tried to access an uninitialized array");
- if (array->fval == 0) {
- sprintf (es, "tried to add a float to %s AwkArray %s",
- array->ival ? "AWK_INT" :
- (array->string ? "AWK_STRING" : "AWK_INDEX"),
- array->name);
- error (NOTFATAL, es);
- return;
- }
- #endif
- array->fval[awkAddIndex (array, key)] = f;
- }
-
- int awkAddIndex (register AwkArray *array, register char *key) {
- /* add a new key to the indexed table. return the index */
- register index;
- register maxindex;
- if (array->remain == 0)
- expandarray (array);
- index = hash (array, key);
- maxindex = array->max - 1;
- #ifdef METER
- array->access += 1;
- access += 1;
- #endif
- while (TRUE) {
- if (!(array->key[index])) {
- array->key[index] = newstring (key);
- array->remain -= 1;
- break;
- }
- else if (awkStrSame (key, array->key[index]))
- break;
- else {
- #ifdef METER
- array->search += 1;
- search += 1;
- #endif
- if (index == maxindex)
- index = 0;
- else
- index += 1;
- }
- }
- return index;
- }
-
- void awkAddInt (AwkArray *array, char *key, int i) {
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkAddInt called prior to awkinit");
- if (array == 0)
- error (AWKFATAL, "awkAddInt: tried to access an uninitialized array");
- if (array->ival == 0) {
- sprintf (es, "tried to add an integer to %s AwkArray %s",
- array->fval ? "AWK_FLOAT" :
- (array->string ? "AWK_STRING" : "AWK_INDEX"),
- array->name);
- error (NOTFATAL, es);
- return;
- }
- #endif
- array->ival[awkAddIndex (array, key)] = i;
- }
-
- void awkAddPointer (AwkArray *array, char *key, void *p) {
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkAddPointer called prior to awkInit");
- if (array == 0)
- error (AWKFATAL,
- "awkAddPointer: tried to access an uninitialized array");
- if (array->string == 0) {
- sprintf (es, "tried to add a string to %s AwkArray %s",
- array->ival ? "AWK_INT" :
- (array->fval ? "AWK_FLOAT" : "AWK_INDEX"),
- array->name);
- error (NOTFATAL, es);
- return;
- }
- #endif
- array->string[awkAddIndex (array, key)] = (char *)p;
- }
-
- void awkAddString (AwkArray *array, char *key, char *s) {
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkAddString called prior to awkInit");
- if (array == 0)
- error (AWKFATAL,"awkAddString: tried to access an uninitialized array");
- if (array->string == 0) {
- sprintf (es, "tried to add a string to %s AwkArray %s",
- array->ival ? "AWK_INT" :
- (array->fval ? "AWK_FLOAT" : "AWK_INDEX"),
- array->name);
- error (NOTFATAL, es);
- return;
- }
- #endif
- array->string[awkAddIndex (array, key)] = newstring (s);
- }
-
- AwkArray *awkNewArray (char *name, int type) {
- /* create a new Array. call newarray to add storage tables */
- AwkArray *array;
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkNewArray called prior to awkInit");
- #endif
- if ((array = (AwkArray*)malloc (sizeof (AwkArray))) == 0) {
- sprintf (es, "malloc failed for array %s", name);
- error (AWKFATAL, es);
- }
- array->max = INITIALSIZE;
- array->remain = REMAIN (array->max);
- array->index = 1;
- array->name = newstring (name);
- array->ival = 0;
- array->fval = 0;
- array->string = 0;
- switch (type) {
- case AWK_INDEX: break;
- case AWK_INT: array->ival = (int*)1; break;
- case AWK_FLOAT: array->fval = (float*)1; break;
- case AWK_STRING:
- case AWK_POINTER: array->string = (char**)1; break;
- default:
- sprintf (es, "array %s has invalid type", name);
- error (AWKFATAL, es);
- break;
- }
- #ifdef METER
- array->access = 0;
- array->search = 0;
- if (arraycount >= MAXARRAY)
- error (AWKFATAL, "too many arrays");
- arraylist[arraycount++] = array;
- storage += sizeof (AwkArray);
- #endif
- return newarray (array);
- }
-
- void awkExit (void) {
- if (STAT)
- _awk_statall ();
- /* XXX - should free all data structures */
- }
-
- void awkFile (char *name) {
- ARGC = 0;
- awkclose ();
- awkopen (name);
- }
-
- void awkInit (int argc, char **argv) {
- /* to be called first */
- int i;
- ARGC = argc;
- ARGV = argv;
- STAT = DEBUG = FALSE;
- awkNL = 0;
- awkNR = 0;
- awkFS = ' ';
- awkRS = '\n';
- awkARG[0] = line;
- for (i=1; i<argc; i++) {
- if (awkStrSame (argv[i], "-DEBUG")) {
- DEBUG = TRUE;
- fprintf (stderr, "awk: version %s, %s\n", VERSION, DATE);
- fprintf (stderr, "awk: debug mode enabled\n");
- argv[i][0] = 0;
- }
- else if (awkStrSame (argv[i], "-STAT")) {
- STAT = TRUE;
- fprintf (stderr, "awk: version %s, %s\n", VERSION, DATE);
- fprintf (stderr, "awk: stat mode enabled\n");
- argv[i][0] = 0;
- }
- else if (awkStrIndex (argv[i], "-F") == 1) {
- awkFS = argv[i][2];
- argv[i][0] = 0;
- }
- }
- awkopennext();
-
- for (i=0; i<128; i++)
- hashval[i] = rand ();
- #ifdef METER
- access = search = storage = arraycount = 0;
- #endif
- awkinited = 1;
- }
-
- int awkStrSame (register char *s1, register char *s2) {
- while (*s1 == *s2++)
- if (*s1++ == 0)
- return TRUE;
- return FALSE;
- }
-
- void awkFirstKey (AwkArray *array) {
- /* prepare for awkNextKey() calls */
- array->index = 1;
- }
-
- float awkGetFloat (AwkArray *array, char *key) {
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkGetFloat called prior to awkInit");
- if (array == 0)
- error (AWKFATAL, "awkGetFloat: tried to access an uninitialized array");
- if (array->fval == 0) {
- sprintf (es, "tried to access a float in %s AwkArray %s",
- array->ival ? "AWK_INT" :
- (array->string ? "AWK_STRING" : "AWK_INDEX"),
- array->name);
- error (NOTFATAL, es);
- return;
- }
- #endif
- return array->fval[awkGetIndex (array, key)];
- }
-
- int awkGetIndex (register AwkArray *array, register char *key) {
- /* return the index of the given key, or zero if no index corresponds */
- register index;
- register maxindex;
- index = hash (array, key);
- maxindex = array->max - 1;
- #ifdef METER
- array->access += 1;
- access += 1;
- #endif
- while (TRUE) {
- if (array->key[index]) {
- if (awkStrSame (key, array->key[index]))
- return index;
- else {
- #ifdef METER
- array->search += 1;
- search += 1;
- #endif
- if (index == maxindex)
- index = 0;
- else
- index += 1;
- }
- }
- else
- return 0;
- }
- }
-
- int awkGetInt (AwkArray *array, char *key) {
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkGetInt called prior to awkInit");
- if (array == 0)
- error (AWKFATAL, "awkGetInt: tried to access an uninitialized array");
- if (array->ival == 0) {
- sprintf (es, "tried to access an integer in %s AwkArray %s",
- array->fval ? "AWK_FLOAT" :
- (array->string ? "AWK_STRING" : "AWK_INDEX"),
- array->name);
- error (NOTFATAL, es);
- return;
- }
- #endif
- return array->ival[awkGetIndex (array, key)];
- }
-
- void *awkGetPointer (AwkArray *array, char *key) {
- register i;
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkGetPointer called prior to awkInit");
- if (array == 0)
- error (AWKFATAL,
- "awkGetPointer: tried to access an uninitialized array");
- if (array->string == 0) {
- sprintf (es, "tried to access a pointer in %s AwkArray %s",
- array->ival ? "AWK_INT" :
- (array->fval ? "AWK_FLOAT" : "AWK_INDEX"),
- array->name);
- error (NOTFATAL, es);
- return 0;
- }
- #endif
- i = awkGetIndex (array, key);
- if (i)
- return (void *)(array->string[i]);
- else
- return 0;
- }
-
- void awkGetString (AwkArray *array, char *key, char *s) {
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkGetString called prior to awkInit");
- if (array == 0)
- error (AWKFATAL,
- "awkGetString: tried to access an uninitialized array");
- if (array->string == 0) {
- sprintf (es, "tried to access a string in %s AwkArray %s",
- array->ival ? "AWK_INT" :
- (array->fval ? "AWK_FLOAT" : "AWK_INDEX"),
- array->name);
- error (NOTFATAL, es);
- return;
- }
- #endif
- strcpy (s, array->string[awkGetIndex (array, key)]);
- }
-
- int awkNextKey (AwkArray *array, char *key) {
- /* returns the 'next' key in the array - call awkFirstKey() to initialize */
- register index, max;
- for (index=array->index, max=array->max; index < max; index++) {
- if (array->key[index]) {
- strcpy (key, array->key[index]);
- array->index = index + 1;
- return TRUE;
- }
- }
- return FALSE;
- }
-
- int awkNextRecord (void) {
- /* read and parse the next input line - return FALSE if no lines left */
-
- register c;
- register i;
- register space;
-
- #ifdef CAREFUL
- if (awkinited == 0)
- error (AWKFATAL, "awkNextRecord called prior to awkInit");
- #endif
- awkNF = 0;
- i = 0;
- space = TRUE;
- while (1) {
- c = getc (infile);
- line[i] = c;
- if (c == '\t')
- c = ' ';
- if (c == EOF) {
- if (i) {
- break;
- }
- awkclose();
- if (awkopennext()) {
- space = TRUE;
- continue;
- }
- else {
- return FALSE;
- }
- }
- else if (c == awkRS) {
- break;
- }
- else if (c == awkFS) {
- if (!space) {
- space = TRUE;
- }
- if (i > MAXARGLEN)
- error (AWKFATAL, "record too long");
- args[i++] = '\0';
- }
- else {
- if (space) {
- space = FALSE;
- awkNF += 1;
- if (awkNF >= MAXARG)
- error (AWKFATAL, "too many fields");
- awkARG[awkNF] = &args[i];
- }
- if (i > MAXARGLEN)
- error (AWKFATAL, "record too long");
- args[i++] = c;
- }
- }
- args[i] = '\0';
- line[i] = '\0';
- if (DEBUG)
- fprintf (stderr, "%s %d: %s\n", awkFILENAME, awkNL, awkARG[0]);
- awkNR += 1;
- awkNL += 1;
- return TRUE;
- }
-
- int awkStrIndex (register char *s1, register char *s2) {
- /*
- * Return the location in s1 at which s2 begins. Return 0 if s2 is
- * not a substring of s1. First location in s1 is 1, not 0.
- */
- register i;
- register char *s, *t;
- register maxi;
- for (maxi=0, s=s1; *s++;)
- maxi += 1;
- for (t=s2; *t++;)
- maxi -= 1;
- for (i=0; i <= maxi; i++) {
- for (s=s1+i, t=s2; ;) {
- if (*t == '\0')
- return (i+1);
- else if (*s++ != *t++)
- break;
- }
- }
- return 0;
- }
-
- void awkSubStr (register char *s1, register char *s2, register m, register n) {
- /*
- * Copy the string starting at the mth character in s2 to s1.
- * Limit the length of this string to n characters. The index
- * of the first character in s1 is 1, not 0.
- */
- for (s2+=(m-1); n--;)
- if (!(*s1++ = *s2++))
- break;
- *s1 = '\0';
- }
-
- /*
- * Internal procedures and functions
- */
-
- static void awkopen (char *s) {
- awkNL = 0;
- if (awkStrSame (s, "-")) {
- strcpy (awkFILENAME, "stdin");
- infile = stdin;
- }
- else {
- strcpy (awkFILENAME, s);
- if ((infile = fopen (s, "r")) == NULL)
- error (AWKFATAL, "cannot open");
- }
- filecount += 1;
- }
-
- static int awkopennext(void) {
- /* open the next input file */
- /* ignore null argv fields */
- /* returns TRUE if a new file was opened, FALSE otherwise */
- static int i = 1;
-
- /* find the next non-null argument and open it */
- for (; i < ARGC;) {
- if (ARGV[i][0]) {
- awkopen (ARGV[i]);
- i += 1;
- return TRUE;
- }
- else
- i += 1;
- }
-
- /* if no non-null fields, and no files have been opened, open stdin */
- if (filecount == 0) {
- awkopen("-");
- return TRUE;
- }
- return FALSE;
- }
-
- static void awkclose (void) {
- if (infile && infile != stdin) {
- fclose (infile);
- strcpy (awkFILENAME, "END");
- }
- }
-
- static void error (int class, char *s) {
- /* print an error message, exit if fatal */
- fprintf (stderr, "awk: file <%s> line %d: %s.", awkFILENAME, awkNL, s);
- if (class == AWKFATAL) {
- fprintf (stderr, " exit.\n\007");
- exit (1);
- }
- else
- fprintf (stderr, "\n");
- }
-
- static void expandarray (AwkArray *array) {
- AwkArray temp;
- char key[MAXKEYLEN+2];
- /* copy the array information to a temporary array */
- temp.max = array->max;
- temp.remain = array->remain;
- temp.index = 1;
- temp.name = array->name;
- temp.key = array->key;
- temp.ival = array->ival;
- temp.fval = array->fval;
- temp.string = array->string;
- /* double the data structure size of the original array */
- array->max = 2 * array->max;
- array->remain = REMAIN (array->max);
- newarray (array);
- /* copy the data from the temp array to the new array */
- if (array->ival) {
- for (awkFirstKey(&temp); awkNextKey(&temp,key);)
- awkAddInt (array, key, awkGetInt (&temp,key));
- free (temp.ival);
- }
- else if (array->fval) {
- for (awkFirstKey(&temp); awkNextKey(&temp,key);)
- awkAddFloat (array, key, awkGetFloat (&temp,key));
- free (temp.fval);
- }
- else if (array->string) {
- for (awkFirstKey(&temp); awkNextKey(&temp,key);)
- awkAddPointer (array, key, awkGetPointer (&temp,key));
- free (temp.string);
- }
- free (temp.key);
- }
-
- static int hash (AwkArray *array, register char *key) {
- /* must return zero for the null string */
- register int *val;
- register i;
- char *s;
- val = hashval;
- s = key;
- for (i=0; *key;)
- i += val[*key++];
- return (array->max * (i&0x3FFF)) >> 14;
- }
-
- static AwkArray *newarray (AwkArray *array) {
- /* malloc and initialize memory for key pointers and data (pointers) */
- register i;
-
- /* allocate and initialize the key pointers */
- if ((array->key = (char**)(malloc (array->max * sizeof (char*)))) == 0) {
- sprintf (es, "malloc failed for array %s", array->name);
- error (AWKFATAL, es);
- }
- for (i=0; i < array->max; i++)
- array->key[i] = 0;
- #ifdef METER
- storage += array->max * sizeof (char*);
- #endif
-
- /* allocate data space if required */
- if (array->ival) {
- if ((array->ival = (int*)malloc (array->max * sizeof (int))) == 0) {
- sprintf (es, "malloc failed for array %s", array->name);
- error (AWKFATAL, es);
- }
- awkAddInt (array, "", 0);
- #ifdef METER
- storage += array->max * sizeof (int);
- #endif
- }
- else if (array->fval) {
- if ((array->fval = (float*)malloc (array->max * sizeof (float))) == 0) {
- sprintf (es, "malloc failed for array %s", array->name);
- error (AWKFATAL, es);
- }
- awkAddFloat (array, "", 0.0);
- #ifdef METER
- storage += array->max * sizeof (float);
- #endif
- }
- else if (array->string) {
- if ((array->string = (char**)malloc (array->max * sizeof (char*)))==0){
- sprintf (es, "malloc failed for array %s", array->name);
- error (AWKFATAL, es);
- }
- awkAddString (array, "", "");
- #ifdef METER
- storage += array->max * sizeof (char*);
- #endif
- }
- return array;
- }
-
- #define MALLOCSIZE 0x1000
-
- static char *newstring (char *s) {
- /* alloc a new string */
- static int avail = 0;
- static char *mem;
- register len;
- register char *t;
-
- for (t=s, len=0; *t++;)
- ;
- len = t - s;
- if (len > avail) {
- if ((mem = (char*)malloc (MALLOCSIZE)) == 0) {
- sprintf (es, "malloc failed for string %s", s);
- error (AWKFATAL, es);
- }
- avail = MALLOCSIZE;
- #ifdef METER
- storage += MALLOCSIZE;
- #endif
- }
- for (t=mem; *t++ = *s++;)
- ;
- t = mem;
- mem += len;
- avail -= len;
- return t;
- }
-
- /*
- * Diagnostic procedures and functions
- */
-
- void _awk_seearray (AwkArray *array) {
- register index;
- printf ("seearray: array address %x\n", array);
- fflush (stdout);
- printf ("array %s:\n max %d\n remain %d\n", array->name,
- array->max, array->remain);
- fflush (stdout);
- for (index=0; index < array->max; index++) {
- printf (" %2d: ", index);
- fflush (stdout);
- if (array->key[index]) {
- printf ("<%s> ", array->key[index]);
- fflush (stdout);
- if (array->ival)
- printf ("%d ", array->ival[index]);
- if (array->fval)
- printf ("%f ", array->fval[index]);
- if (array->string) {
- if (array->string[index])
- printf ("<%s> ", array->string[index]);
- else
- printf ("<null pointer>");
- }
- fflush (stdout);
- }
- printf ("\n");
- }
- }
-
- void _awk_statall (void) {
- int i;
- AwkArray *array;
- #ifdef METER
- fprintf (stderr, "STATISTICS:\n");
- for (i=0; i<arraycount; i++) {
- array = (AwkArray*)arraylist[i];
- fprintf (stderr, "%16s: %5d locations, ", array->name, array->max);
- fprintf (stderr,"%8d accesses, %5.2f searches/access\n",
- array->access, (float)(array->search) / (float)(array->access));
- }
- fprintf (stderr, "%8d total accessses\n", access);
- fprintf (stderr, "%8d total searches\n", search);
- fprintf (stderr, " %7.2f searches/access\n",(float)search/(float)access);
- #else
- fprintf (stderr, "WARNING: no statistics kept!\n");
- #endif
- }
-